//****************************************************
// Porman Project 2
// Filename: CTextureObject.h
// Date: 2009/03/01
// Author: KengYu Lin
// Modify:
//****************************************************
#ifndef _CTEXTUREOBJECT_H
#define _CTEXTUREOBJECT_H
#include "CBaseObject.h"

namespace Porman
{

namespace GL
{

//----------------------------
// class CSamplerState
//----------------------------
class CSamplerState
{
    friend class CTextureBaseObject;
private:
    enum ESampler {
        E_WRAP_S = GL_TEXTURE_WRAP_S,
        E_WRAP_T = GL_TEXTURE_WRAP_T,
        E_WRAP_R = GL_TEXTURE_WRAP_R,

        E_MAG_FILTER = GL_TEXTURE_MAG_FILTER,
        E_MIN_FILTER = GL_TEXTURE_MIN_FILTER,

        E_BORDER_COLOR = GL_TEXTURE_BORDER_COLOR
    };

public:
    PGL_API CSamplerState( void );
    PGL_API CSamplerState( const CSamplerState& l );
    PGL_API virtual ~CSamplerState( void ) {}

    PGL_API void reset( void );
    PGL_API CSamplerState& operator= (const CSamplerState& l);
    PGL_API bool operator==( const CSamplerState& l );
    PGL_API bool operator!=( const CSamplerState& l );

public:
    ECoordWrap    m_eCoordWrap_s;
    ECoordWrap    m_eCoordWrap_r;
    ECoordWrap    m_eCoordWrap_t;

    EMagFilter    m_eMagFilter;
    EMinFilter    m_eMinFilter;
    EMipMapFilter m_eMipMapFilter;

    float         m_fBorderColor[4];
    float         m_fAnisotropicVal;
};

//----------------------------
// class CTextureBaseObject
//----------------------------
class CTextureBaseObject : public CBaseObject
{
    friend class CRenderDevice;
    friend class CShaderObject;
    friend class CFXObject;
public:
    PGL_API virtual void setName( const char* pName ) { m_sName = std::string("TexObj_") + std::string( pName ); }
    PGL_API ETexType getTexType( void ) { return m_eType; }

protected:
    CTextureBaseObject( CRenderDevice* pDevice, ETexType enumType );
    virtual ~CTextureBaseObject( void );

    ERESULT _setSamplerState( const CSamplerState& Sampler, bool bCheck = true );
    unsigned int _sizeof( EDataFormat enumFormat );
    unsigned int _getGLFormat( EDataFormat enumFormat );
    unsigned int _getGLType( EDataFormat enumFormat );

protected:
    unsigned int m_uiObjID;
    unsigned int m_uiBufID;
    ETexType m_eType;
    CSamplerState m_Sampler;
    int m_iNumOfMipmap;
};

//----------------------------
// class CTexture2DObject
//----------------------------
class CTexture2DObject : public CTextureBaseObject
{
    friend class CRenderDevice;
    friend class CShaderObject;
    friend class CFXObject;
public:
    struct STexture2DDesc
    {
    public:
        STexture2DDesc( int iNumMipmap, int iWidth, int iHeight, int iBorder, EInterFormat enumInterFormat ) :
        m_iNumMipmap(iNumMipmap),
        m_iWidth(iWidth),
        m_iHeight(iHeight),
        m_iBorder(iBorder),
        m_eInterFormat(enumInterFormat)
        {}

        int m_iNumMipmap;
        int m_iWidth;
        int m_iHeight;
        int m_iBorder;
        EInterFormat m_eInterFormat;
    };

    struct STexture2DLevelDesc
    {
    public:
        STexture2DLevelDesc( void ) : m_iWidth(0), m_iHeight(0), m_iBorder(0), m_eInterFormat(E_INTERFORMAT_NON) {}

        int m_iWidth;
        int m_iHeight;
        int m_iBorder;
        EInterFormat m_eInterFormat;
    };

public:
    PGL_API ERESULT getLevelDesc( int iLevel, STexture2DLevelDesc& Desc );
    PGL_API ERESULT setData( int iLevel, int iXOffset, int iYOffset, int iWidth, int iHeight, EDataFormat enumDataFormat, void* pData );
    PGL_API ERESULT getData( int iLevel, int iXOffset, int iYOffset, int iWidth, int iHeight, EDataFormat enumDataFormat, void* pData );

protected:
    CTexture2DObject( CRenderDevice* pDevice, STexture2DDesc& Desc );
    virtual ~CTexture2DObject( void );

protected:
    STexture2DLevelDesc* m_pLevelDescTable;
};

//----------------------------
// class CTexture3DObject
//----------------------------
class CTexture3DObject : public CTextureBaseObject
{
    friend class CRenderDevice;
    friend class CShaderObject;
    friend class CFXObject;
public:
    struct STexture3DDesc
    {
    public:
        STexture3DDesc( int iNumMipmap, int iWidth, int iHeight, int iDepth, int iBorder, EInterFormat enumInterFormat ) :
        m_iNumMipmap(iNumMipmap),
        m_iWidth(iWidth),
        m_iHeight(iHeight),
        m_iDepth(iDepth),
        m_iBorder(iBorder),
        m_eInterFormat(enumInterFormat)
        {}

        int m_iNumMipmap;
        int m_iWidth;
        int m_iHeight;
        int m_iDepth;
        int m_iBorder;
        EInterFormat m_eInterFormat;
    };

    struct STexture3DLevelDesc
    {
    public:
        STexture3DLevelDesc( void ) : m_iWidth(0), m_iHeight(0), m_iDepth(0), m_iBorder(0), m_eInterFormat(E_INTERFORMAT_NON) {}

        int m_iWidth;
        int m_iHeight;
        int m_iDepth;
        int m_iBorder;
        EInterFormat m_eInterFormat;
    };

public:
    PGL_API ERESULT getLevelDesc( int iLevel, STexture3DLevelDesc& Desc );
    PGL_API ERESULT setData( int iLevel, int iXOffset, int iYOffset, int iZOffset, int iWidth, int iHeight, int iDepth, EDataFormat enumDataFormat, void* pData );
    PGL_API ERESULT getData( int iLevel, int iXOffset, int iYOffset, int iZOffset, int iWidth, int iHeight, int iDepth, EDataFormat enumDataFormat, void* pData );

protected:
    CTexture3DObject( CRenderDevice* pDevice, STexture3DDesc& Desc );
    virtual ~CTexture3DObject( void );

protected:
    STexture3DLevelDesc* m_pLevelDescTable;
};

//----------------------------
// class CTextureCubeObject
//----------------------------
class CTextureCubeObject : public CTextureBaseObject
{
    friend class CRenderDevice;
    friend class CShaderObject;
    friend class CFXObject;
public:
    enum ETexCubeFace {
        E_POSITIVE_X = GL_TEXTURE_CUBE_MAP_POSITIVE_X,
        E_NEGATIVE_X = GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
        E_POSITIVE_Y = GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
        E_NEGATIVE_Y = GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
        E_POSITIVE_Z = GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
        E_NEGATIVE_Z = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
    };

    struct STextureCubeDesc
    {
    public:
        STextureCubeDesc( int iNumMipmap, int iWidth, int iHeight, int iBorder, EInterFormat enumInterFormat ) :
        m_iNumMipmap(iNumMipmap),
        m_iWidth(iWidth),
        m_iHeight(iHeight),
        m_iBorder(iBorder),
        m_eInterFormat(enumInterFormat)
        {}

        int m_iNumMipmap;
        int m_iWidth;
        int m_iHeight;
        int m_iBorder;
        EInterFormat m_eInterFormat;
    };

    struct STextureCubeLevelDesc
    {
    public:
        STextureCubeLevelDesc( void ) : m_iWidth(0), m_iHeight(0), m_iBorder(0), 
                                        m_eFace(E_POSITIVE_X), m_eInterFormat(E_INTERFORMAT_NON) {}

        int m_iWidth;
        int m_iHeight;
        int m_iBorder;
        ETexCubeFace m_eFace;
        EInterFormat m_eInterFormat;
    };

public:
    PGL_API ERESULT getLevelDesc( ETexCubeFace enumFace, int iLevel, STextureCubeLevelDesc& Desc );
    PGL_API ERESULT setData( ETexCubeFace enumFace, int iLevel, int iXOffset, int iYOffset, int iWidth, int iHeight, EDataFormat enumDataFormat, void* pData );
    PGL_API ERESULT getData( ETexCubeFace enumFace, int iLevel, int iXOffset, int iYOffset, int iWidth, int iHeight, EDataFormat enumDataFormat, void* pData );

protected:
    CTextureCubeObject( CRenderDevice* pDevice, STextureCubeDesc& Desc );
    virtual ~CTextureCubeObject( void );
    int _getIndexOfFace( ETexCubeFace enumFace );

protected:
    STextureCubeLevelDesc** m_ppLevelDescTable[6];
};

}//End namespace GL

}//End namespace Porman

#endif